# -*- coding: utf-8 -*-
# Created Time : 2021/3/9 22:57
# Author:Zhou

# 有一堆石头，每块石头的重量都是正整数。
#
# 每一回合，从中选出任意两块石头，然后将它们一起粉碎。假设石头的重量分别为x 和y，且x <= y。那么粉碎的可能结果如下：
#
# 如果x == y，那么两块石头都会被完全粉碎；
# 如果x != y，那么重量为x的石头将会完全粉碎，而重量为y的石头新重量为y-x。
# 最后，最多只会剩下一块石头。返回此石头最小的可能重量。如果没有石头剩下，就返回 0。
#
# 来源：力扣（LeetCode）
# 链接：https://leetcode-cn.com/problems/last-stone-weight-ii
# 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。

# 输入：[2,7,4,1,8,1]
# 输出：1
# 解释：
# 组合 2 和 4，得到 2，所以数组转化为 [2,7,1,8,1]，
# 组合 7 和 8，得到 1，所以数组转化为 [2,1,1,1]，
# 组合 2 和 1，得到 1，所以数组转化为 [1,1,1]，
# 组合 1 和 1，得到 0，所以数组转化为 [1]，这就是最优值。

# 1 <= stones.length <= 30
# 1 <= stones[i] <= 1000

from typing import List


class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:
        """
        分成最相近的两堆石头
        转化成0-1背包问题
        dp[j]: j背包容量
        dp[j] = max([j],dp[j-stones[i]]+stones[i]) 取或不取第i块石头
        values[i] weight[i] 都等于 stones[i]
        """
        stonesSum = sum(stones)
        target = stonesSum // 2
        dp = [0] * (target + 1)
        for i in range(len(stones)):  # 遍历物品
            for j in range(target, stones[i] - 1, -1):  # 遍历背包容量 从后往前
                dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
        return (stonesSum - dp[target]) - dp[target]  # 两堆的差


if __name__ == '__main__':
    sol = Solution()
    print(sol.lastStoneWeightII([2, 7, 4, 1, 8, 1]))
    print(sol.lastStoneWeightII([31, 26, 33, 21, 40]))
